
/* GCSx
** MEM.H
**
** Memory functions that perform full error reporting and garbage collection
*/

/*****************************************************************************
** Copyright (C) 2003-2006 Janson
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
*****************************************************************************/

#ifndef __GCSx_MEM_H_
#define __GCSx_MEM_H_

#ifndef NDEBUG
#define MEMDEBUG
#endif

// Handles "graceful" exit upon crash- does NOT return
// MemoryError indicates whether this is a memory error (can't use new)
void fatalCrash(int memoryError, const char* title, ...);

#ifndef MEMDEBUG

// Our memory management with exceptions and garbage collection and debugging
// The regular versions "crash" if memory runs out
// The nothrow versions simply return NULL
void* operator new(std::size_t size);
void* operator new[](std::size_t size);
void operator delete(void* ptr);
void operator delete[](void* ptr);
void* operator new(std::size_t size, const std::nothrow_t&);
void* operator new[](std::size_t size, const std::nothrow_t&);
void operator delete(void* ptr, const std::nothrow_t&);
void operator delete[](void* ptr, const std::nothrow_t&);

// Placeholder if nodebugging
#define start_func

#else

// Debugging memory routines
void* new_debug(std::size_t size, int array, int noThrow);
void new_delete(void* ptr, int array);
inline void* operator new(std::size_t size) { return new_debug(size, 0, 0); }
inline void* operator new[](std::size_t size) { return new_debug(size, 1, 0); }
inline void operator delete(void* ptr) { return new_delete(ptr, 0); }
inline void operator delete[](void* ptr) { return new_delete(ptr, 1); }
inline void* operator new(std::size_t size, const std::nothrow_t&) { return new_debug(size, 0, 1); }
inline void* operator new[](std::size_t size, const std::nothrow_t&) { return new_debug(size, 1, 1); }
inline void operator delete(void* ptr, const std::nothrow_t&) { return new_delete(ptr, 0); }
inline void operator delete[](void* ptr, const std::nothrow_t&) { return new_delete(ptr, 1); }

// Debugging memory AND trace
class function_begin_end {
public:
    static int level;
    const char* name;
    const char* previous;
    function_begin_end(const char* n);
    ~function_begin_end();
};
#ifdef __GNUC__
#define start_func function_begin_end my_function_begin_end(__PRETTY_FUNCTION__);
#else
#define start_func function_begin_end my_function_begin_end(__func__);
#endif

// Set a point at which we track all further mem allocations
void enableMemListTrack();
// Call this at the same point during exit, to check for leaks
void memLeakCheck();
// Returns true if ANY memory errors/leaks have been caught yet
// (doesn't count out-of-memory exceptions as one)
int memDebugAnyErrors();

// If debugging is enabled, we also have a way
// to throw exceptions at a threshold
void setMemThreshold(std::size_t thresh);

#endif

#endif

